package com.sqtracker.recommender.service;

import com.sqtracker.recommender.dto.UserPreferenceDTO;
import com.sqtracker.recommender.model.UserBehavior;
import com.sqtracker.recommender.model.UserPreference;
import com.sqtracker.recommender.repository.TorrentMetadataExtRepository;
import com.sqtracker.recommender.repository.UserBehaviorRepository;
import com.sqtracker.recommender.repository.UserPreferenceRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class UserPreferenceService {

    private final UserPreferenceRepository userPreferenceRepository;
    private final UserBehaviorRepository userBehaviorRepository;
    private final TorrentMetadataExtRepository torrentMetadataExtRepository;

    @Autowired
    public UserPreferenceService(
            UserPreferenceRepository userPreferenceRepository,
            UserBehaviorRepository userBehaviorRepository,
            TorrentMetadataExtRepository torrentMetadataExtRepository) {
        this.userPreferenceRepository = userPreferenceRepository;
        this.userBehaviorRepository = userBehaviorRepository;
        this.torrentMetadataExtRepository = torrentMetadataExtRepository;
    }

    /**
     * 获取用户偏好
     */
    public UserPreference getUserPreference(String userId) {
        Optional<UserPreference> preference = userPreferenceRepository.findByUserId(userId);

        if (preference.isPresent()) {
            return preference.get();
        }
        System.out.println(userId);


        // 如果没有找到偏好设置，则创建一个新的
        UserPreference newPreference = new UserPreference();
        newPreference.setUserId(userId);
        newPreference.setExplicitPreferences(new UserPreference.ExplicitPreferences());
        newPreference.setImplicitPreferences(new UserPreference.ImplicitPreferences());
        newPreference.setLastUpdated(new Date());

        // 根据用户行为计算隐式偏好
        updateImplicitPreferences(newPreference);

        return userPreferenceRepository.save(newPreference);
    }

    /**
     * 保存用户偏好
     */
    public void saveUserPreference(UserPreferenceDTO preferenceDTO) {
        String userId = preferenceDTO.getUserId();
        UserPreference preference = getUserPreference(userId);

        // 更新显式偏好
        UserPreference.ExplicitPreferences explicitPrefs = preference.getExplicitPreferences();
        if (explicitPrefs == null) {
            explicitPrefs = new UserPreference.ExplicitPreferences();
            preference.setExplicitPreferences(explicitPrefs);
        }

        UserPreferenceDTO.ExplicitPreferences dtoPrefs = preferenceDTO.getExplicitPreferences();
        if (dtoPrefs != null) {
            explicitPrefs.setCategories(dtoPrefs.getCategories());
            explicitPrefs.setTags(dtoPrefs.getTags());
            explicitPrefs.setLanguages(dtoPrefs.getLanguages());
            explicitPrefs.setQuality(dtoPrefs.getQuality());
        }

        preference.setLastUpdated(new Date());


        // 更新隐式偏好
        updateImplicitPreferences(preference);

        userPreferenceRepository.save(preference);
    }

    /**
     * 重置用户偏好
     */
    public void resetUserPreference(String userId) {
        userPreferenceRepository.deleteByUserId(userId);
    }

    /**
     * 获取可用的偏好选项
     */
    public Map<String, Object> getPreferenceOptions() {
        Map<String, Object> options = new HashMap<>();

        // 这里应该从实际数据中获取，这里只是示例
        options.put("categories", Arrays.asList(
                Map.of("id", "movie", "name", "电影"),
                Map.of("id", "tv", "name", "电视剧"),
                Map.of("id", "music", "name", "音乐"),
                Map.of("id", "game", "name", "游戏"),
                Map.of("id", "software", "name", "软件"),
                Map.of("id", "book", "name", "书籍"),
                Map.of("id", "other", "name", "其他")
        ));

        options.put("languages", Arrays.asList(
                Map.of("id", "zh-CN", "name", "简体中文"),
                Map.of("id", "zh-TW", "name", "繁体中文"),
                Map.of("id", "en", "name", "英语"),
                Map.of("id", "ja", "name", "日语"),
                Map.of("id", "ko", "name", "韩语"),
                Map.of("id", "fr", "name", "法语"),
                Map.of("id", "de", "name", "德语")
        ));

        options.put("quality", Arrays.asList(
                Map.of("id", "1080p", "name", "1080P"),
                Map.of("id", "720p", "name", "720P"),
                Map.of("id", "4k", "name", "4K"),
                Map.of("id", "hdr", "name", "HDR"),
                Map.of("id", "sd", "name", "标清")
        ));

        // 从数据库获取热门标签
        options.put("tags", getPopularTags(20));

        return options;
    }

    /**
     * 更新隐式偏好
     */
    private void updateImplicitPreferences(UserPreference preference) {
        String userId = preference.getUserId();

        // 获取用户行为
        List<UserBehavior> behaviors = userBehaviorRepository.findByUserId(userId);

        // 构建类别、标签、语言、发布者权重
        Map<String, Double> categoryWeights = new HashMap<>();
        Map<String, Double> tagWeights = new HashMap<>();
        Map<String, Double> languageWeights = new HashMap<>();
        Map<String, Double> publisherWeights = new HashMap<>();

        // 根据用户行为计算权重
        for (UserBehavior behavior : behaviors) {
            String torrentId = behavior.getTorrentId();
            double weight = getBehaviorWeight(behavior.getType());

            // 获取种子元数据并更新权重
            torrentMetadataExtRepository.findByTorrentId(torrentId).ifPresent(metadata -> {
                // 更新分类权重
                if (metadata.getTorrentCategoryId() != null) {
                    String category = metadata.getTorrentCategoryId();
                    categoryWeights.put(category, categoryWeights.getOrDefault(category, 0.0) + weight);
                }

                // 更新标签权重
                if (metadata.getTags() != null) {
                    for (String tag : metadata.getTags()) {
                        tagWeights.put(tag, tagWeights.getOrDefault(tag, 0.0) + weight);
                    }
                }

                // 更新语言权重
                if (metadata.getLanguage() != null) {
                    String language = metadata.getLanguage();
                    languageWeights.put(language, languageWeights.getOrDefault(language, 0.0) + weight);
                }
            });
        }

        // 正规化权重
        normalizeWeights(categoryWeights);
        normalizeWeights(tagWeights);
        normalizeWeights(languageWeights);
        normalizeWeights(publisherWeights);

        // 设置隐式偏好
        UserPreference.ImplicitPreferences implicitPrefs = preference.getImplicitPreferences();
        if (implicitPrefs == null) {
            implicitPrefs = new UserPreference.ImplicitPreferences();
            preference.setImplicitPreferences(implicitPrefs);
        }

        implicitPrefs.setCategories(categoryWeights);
        implicitPrefs.setTags(tagWeights);
        implicitPrefs.setLanguages(languageWeights);
        implicitPrefs.setPublishers(publisherWeights);
    }

    /**
     * 获取行为权重
     */
    private double getBehaviorWeight(String behaviorType) {
        switch (behaviorType) {
            case "DOWNLOAD":
                return 5.0;
            case "LIKE":
                return 3.0;
            case "RATE":
                return 2.0;
            case "VIEW":
                return 1.0;
            default:
                return 0.5;
        }
    }

    /**
     * 正规化权重
     */
    private void normalizeWeights(Map<String, Double> weights) {
        if (weights.isEmpty()) {
            return;
        }

        // 找出最大值
        double maxWeight = weights.values().stream().max(Double::compare).orElse(1.0);

        // 正规化为0-1范围
        for (Map.Entry<String, Double> entry : weights.entrySet()) {
            weights.put(entry.getKey(), entry.getValue() / maxWeight);
        }
    }

    /**
     * 获取热门标签
     */
    private List<Map<String, String>> getPopularTags(int limit) {
        // 这里应该从实际数据中获取，这里只是示例
        return Arrays.asList(
                Map.of("id", "action", "name", "动作"),
                Map.of("id", "comedy", "name", "喜剧"),
                Map.of("id", "drama", "name", "剧情"),
                Map.of("id", "sci-fi", "name", "科幻"),
                Map.of("id", "horror", "name", "恐怖"),
                Map.of("id", "romance", "name", "爱情"),
                Map.of("id", "animation", "name", "动画"),
                Map.of("id", "documentary", "name", "纪录片"),
                Map.of("id", "thriller", "name", "惊悚"),
                Map.of("id", "crime", "name", "犯罪")
        );
    }
}